#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <asl.h>
#import <UIKit/UIApplication.h>
#import <LockInfo/Plugin.h>

#import "framework/FWCommon.h"
#import "framework/FWDetailListEntry.h"
#import "framework/FWDetailListSection.h"
#import "framework/FWPlugin.h"

#import "PICommon.h"
#import "PIPlugin.h"
#import "PIDebugView.h"


static NSString* const kPluginPrefsPage = @"Plugin";
static NSString* const kPIPrefsPage = @"PI";
static NSString* const kLIPrefsPage = @"LI";
static NSString* const kConsolePage = @"Console";


@implementation PIDebugView

@synthesize pasteInfo, controlDelegate;


// ******************************************************************************************
#pragma mark -
#pragma mark Initialisation and object management

- (void)dealloc
{
    [pasteInfo release];
    [controlDelegate release];
    
    [super dealloc];
}

// ******************************************************************************************
#pragma mark -
#pragma mark Handling user input

- (BOOL)doneClicked:(FWApplication*)application sections:(NSArray*)sections
{
    if (pasteInfo) {
        UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
        pasteboard.string = pasteInfo;

        [controlDelegate displayPopupInstruction:localize([NSBundle bundleForClass:[self class]], @"Debug View/Copied")];

        return NO;
    }
    
    return YES;
}


// ******************************************************************************************
#pragma mark -
#pragma mark Standard debug info

- (NSArray*)console
{
    NSString *startTime = [NSString stringWithFormat:@"%.0f", [[NSDate dateWithTimeIntervalSinceNow:-60*SECONDS_IN_HOUR]
                                                               timeIntervalSince1970]];
    
    NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
    dateFormatter.dateStyle = NSDateFormatterNoStyle;
    dateFormatter.timeStyle = NSDateFormatterMediumStyle;
    dateFormatter.locale = [NSLocale systemLocale];
    
    NSString* processID = [NSString stringWithFormat:@"%i", [[NSProcessInfo processInfo] processIdentifier]];
    
    NSMutableArray *logStrings = [NSMutableArray array];
    
    aslclient client = asl_open(NULL, NULL, ASL_OPT_STDERR);
    
    aslmsg query = asl_new(ASL_TYPE_QUERY);
    //    asl_set_query(query, ASL_KEY_MSG, NULL, ASL_QUERY_OP_NOT_EQUAL);
    asl_set_query(query, ASL_KEY_PID, [processID UTF8String], ASL_QUERY_OP_EQUAL);
    //    asl_set_query(query, ASL_KEY_SENDER, "com.apple.springboard", ASL_QUERY_OP_EQUAL);
    asl_set_query(query, ASL_KEY_TIME, [startTime UTF8String], ASL_QUERY_OP_GREATER_EQUAL);
    aslresponse response = asl_search(client, query);
    asl_free(query);
    
    aslmsg msg;
    NSDate* lastTime = nil;
    while ((msg = aslresponse_next(response))) {
        const char* cTime = asl_get(msg, ASL_KEY_TIME);
        const char *cMsg = asl_get(msg, ASL_KEY_MSG);
        //        const char *cSender = asl_get(msg, ASL_KEY_SENDER);
        
        if (cTime && cMsg) {
            NSDate* time = [NSDate dateWithTimeIntervalSince1970:[[NSString stringWithCString:cTime
                                                                                     encoding:NSUTF8StringEncoding] doubleValue]];
            if (lastTime && ((int)[time timeIntervalSinceDate:lastTime] > 10))
                [logStrings addObject:@"############################################"];
                
            [logStrings addObject:[NSString stringWithFormat:@"%@ %s", [dateFormatter stringFromDate:time], cMsg]];
            lastTime = time;
        }
    }
    
    aslresponse_free(response);
    
    asl_close(client);
    
    return logStrings;
}

- (NSArray*)dataForDetailListPage:(NSObject *)page key:(NSObject*)key application:(FWApplication *)application
{  
    NSBundle* bundle = [NSBundle bundleForClass:[self class]];

    PIPlugin* plugin = (PIPlugin*)application.fwPlugin;

    NSArray* infoSect = [NSArray arrayWithObjects:
                         [FWDetailListEntry entryWithLocalisedTitle:@"Debug View/Version"
                                                              value:plugin.isNativeOnly ? @"--" : (plugin.isPocketInformant2 ? @"2" : @"1")
                                                             bundle:bundle],
                         nil];

    NSMutableArray* prefsSect = [NSMutableArray arrayWithObject:
                          [[FWDetailListEntry entryWithLocalisedTitle:@"Debug View/Prefs" bundle:bundle]
                            withLinkType:kPluginPrefsPage]];

    if (plugin.isPocketInformantPresent && !plugin.isNativeOnly)
        [prefsSect addObject:[[FWDetailListEntry entryWithLocalisedTitle:@"Debug View/PI Prefs" bundle:bundle]
                              withLinkType:kPIPrefsPage]];

    [prefsSect addObject:[[FWDetailListEntry entryWithLocalisedTitle:@"Debug View/LI Prefs" bundle:bundle]
                          withLinkType:kLIPrefsPage]];
    
    NSArray* logsSect = [NSArray arrayWithObject:
                         [[FWDetailListEntry entryWithLocalisedTitle:@"Debug View/Console" bundle:bundle]
                          withLinkType:kConsolePage]];
    

    NSMutableArray* display = [NSMutableArray arrayWithObjects:
                               [FWDetailListSection sectionForElements:infoSect],
                               [FWDetailListSection sectionForElements:prefsSect withTitle:localize(bundle, @"Debug View/Preferences")],
                               [FWDetailListSection sectionForElements:logsSect],
                               nil];
    
    NSArray* extras = [self detailSectionsForListPage:page key:key application:application];
    if (extras)
        [display addObjectsFromArray:extras];
    
    NSTimeZone* tz = [NSTimeZone systemTimeZone];
    NSDate* now = [NSDate date];
    NSDate *localMidnight = FWLocalDateForLocalMidnight();
    NSDate *utcMidnight = FWUTCForLocalDate(localMidnight);
    
    NSArray* info = [NSArray arrayWithObjects:
                     [FWDetailListEntry entryWithTitle:@"Language"
                                                 value:[[NSLocale preferredLanguages] objectAtIndex:0]],
                     [FWDetailListEntry entryWithTitle:@"TZ name"
                                                 value:tz.name],
                     [FWDetailListEntry entryWithTitle:@"TZ code"
                                                 value:tz.abbreviation],
                     [FWDetailListEntry entryWithTitle:@"Offset"
                                                 value:[NSNumber numberWithInt:tz.secondsFromGMT]],
                     [FWDetailListEntry entryWithTitle:@"Now"
                                                 value:now.description],
                     [FWDetailListEntry entryWithTitle:@"Start"
                                                 value:utcMidnight.description],
                     [FWDetailListEntry entryWithTitle:@"UTC"
                                                 value:localMidnight.description],
                     [FWDetailListEntry entryWithTitle:@"DST"
                                                 value:[NSNumber numberWithBool:tz.isDaylightSavingTime]],
                     nil];
    
    [display addObject:[FWDetailListSection sectionForElements:info withTitle:localize(bundle, @"Debug View/Time")]];
    
    return display;
}

- (NSString*)captionForListPage:(NSObject *)page forKey:(NSObject *)key displayDepth:(NSInteger)depth application:(FWApplication *)application
{
    NSBundle* bundle = [NSBundle bundleForClass:[self class]];
    
    if ([(NSString*)key isEqualToString:kPluginPrefsPage])
        return localize(bundle, @"Debug View/Prefs Title");
    else if ([(NSString*)key isEqualToString:kPIPrefsPage])
        return localize(bundle, @"Debug View/PI Title");
    else if ([(NSString*)key isEqualToString:kLIPrefsPage])
        return localize(bundle, @"Debug View/LI Title");
    else if ([(NSString*)key isEqualToString:kConsolePage])
        return localize(bundle, @"Debug View/Log Title");
    
    return nil;
}

- (NSString*)listPageTextForKey:(NSObject*)key currentPage:(NSObject*)current displayDepth:(NSInteger)depth application:(FWApplication*)application
{
    self.pasteInfo = nil;
    
    if ([(NSString*)key isEqualToString:kPluginPrefsPage]) {
        self.pasteInfo = [application.fwPlugin.liPlugin.preferences description];
    }
    else if ([(NSString*)key isEqualToString:kPIPrefsPage]) {
        NSDictionary* applicationPrefs = [NSDictionary dictionaryWithContentsOfFile:application.preferencesPath];
        self.pasteInfo = [applicationPrefs description];
    }
    else if ([(NSString*)key isEqualToString:kLIPrefsPage]) {
        self.pasteInfo = [application.fwPlugin.liPlugin.globalPreferences description];
    }
    else if ([(NSString*)key isEqualToString:kConsolePage]) {
        self.pasteInfo = [[self console] componentsJoinedByString:@"\n"];
    }
    
    return pasteInfo;
}

- (BOOL)listPageTextScrollToEndForKey:(NSObject *)key currentPage:(NSObject *)page displayDepth:(NSInteger)depth application:(FWApplication *)application
{
    if ([(NSString*)key isEqualToString:kConsolePage])
        return YES;
    else
        return NO;
}

- (NSString*)doneButtonCaptionForKey:(NSObject *)key currentPage:(NSObject *)page displayDepth:(NSInteger)depth application:(FWApplication *)application
{
    if ([(NSString*)key isEqualToString:kConsolePage] ||
        [(NSString*)key isEqualToString:kPIPrefsPage] ||
        [(NSString*)key isEqualToString:kLIPrefsPage] ||
        [(NSString*)key isEqualToString:kPluginPrefsPage])
        return localize([NSBundle bundleForClass:[self class]], @"Detail/Button/Copy");
    else
        return nil;
}

- (void)willShowBasePage:(NSObject *)page
{
    self.pasteInfo = nil;
}

- (NSArray*)detailSectionsForListPage:(NSObject *)page key:(NSObject *)key application:(FWApplication *)application
{
    return nil;
}

@end
